/*
 * ShotHttpSender.cpp
 *
 *  Created on: Oct 7, 2012
 *      Author: Administrator
 */

#include "ShotHttpSender.h"
#include "Util.h"

using namespace Osp::Base;
using namespace Osp::Base::Utility;
using namespace Osp::Base::Runtime;
using namespace Osp::Base::Collection;
using namespace Osp::Net::Http;
using namespace Osp::Net::Sockets;
using namespace Osp::Net;

ShotHttpSender::ShotHttpSender() {

	String* pProxyAddr = null;
	String hostAddr = L"http://192.168.0.184:8080";
	session = new HttpSession();
	session->Construct(NET_HTTP_SESSION_MODE_NORMAL, pProxyAddr, hostAddr, null);

	store = Util::GetShotStore();
	Construct();
	Start();
	SendUserEvent(1, null);

}

ShotHttpSender::ShotHttpSender(HttpSession* pSession, String pHostAddr) {
	session = pSession;
	hostAddr = pHostAddr;
	store = Util::GetShotStore();
	Construct();
	Start();
	SendUserEvent(1, null);
}

ShotHttpSender::~ShotHttpSender() {
	AppLog("Destroying ShotHttpSender");
}

void
ShotHttpSender::OnTransactionAborted (HttpSession &httpSession, HttpTransaction &httpTransaction, result r) {
	AppLog("OnTransactionAborted");
}

void
ShotHttpSender::OnTransactionCertVerificationRequiredN (HttpSession &httpSession, HttpTransaction &httpTransaction, Osp::Base::String *pCert){
	AppLog("OnTransactionCertVerificationRequiredN");
}

void
ShotHttpSender::OnTransactionCompleted (HttpSession &httpSession, HttpTransaction &httpTransaction) {
	AppLog("OnTransactionCompleted");
	delete &httpTransaction;
	store->DeleteShot(shot->GetName());
	SendUserEvent(1, null);
}

void
ShotHttpSender::OnTransactionHeaderCompleted (HttpSession &httpSession, HttpTransaction &httpTransaction, int headerLen, bool bAuthRequired) {
	AppLog("OnTransactionHeaderCompleted");
}

void
ShotHttpSender::OnTransactionReadyToRead (HttpSession &httpSession, HttpTransaction &httpTransaction, int availableBodyLen) {
//	HttpTransaction* pTransaction = const_cast<HttpTransaction*>(&(httpTransaction));
//	HttpResponse* pResponse = pTransaction->GetResponse();
//	ByteBuffer* pBody = null;
//	String statusText;
//	String version;
//	if(pResponse->GetHttpStatusCode() == HTTP_STATUS_OK)
//	{
//		statusText = pResponse->GetStatusText();
//		version = pResponse->GetVersion();
//		pBody = pResponse->ReadBodyN();
//		byte b;
//		pBody->GetByte(b);
//		AppLog("Response text is %d", b);
//		delete pBody;
//	}
}

void
ShotHttpSender::OnTransactionReadyToWrite (HttpSession &httpSession, HttpTransaction &httpTransaction, int recommendedChunkSize) {

	AppLog("OnTransactionReadyToWrite");
	HttpTransaction* pTransaction = &httpTransaction;
	HttpRequest* pRequest = pTransaction->GetRequest();
	result r = E_SUCCESS;

	ByteBuffer* data = shot->GetBytes();
	ByteBuffer* portion = new ByteBuffer();

	if(data->GetRemaining()==0)
	{
		//Set a last chunked flag.
		AppLog("Sending the last chunk");
		ByteBuffer* body = new ByteBuffer();
		body->Construct(0);
		body->Flip();
		r =pRequest->WriteBody(*body);
		delete body;
		shot->~Shot();
	} else {
		//Set a chunked data.
		int size = Math::Min(recommendedChunkSize, data->GetRemaining());
		portion -> Construct(size);
		AppLog("Sending with size %d (recommended %d)", size, recommendedChunkSize);

		while(portion->GetPosition()<size) {
			byte b;
			data->GetByte(b);
			portion->SetByte(b);
		}
		portion->Flip();
		pRequest->WriteBody(*portion);
		delete portion;
	}

}

result
ShotHttpSender::Construct(void) {
	result r = E_SUCCESS;
	r = Thread::Construct(THREAD_TYPE_EVENT_DRIVEN);
	AppLog("ShotHttpSender start result %s", GetErrorMessage(r));
	return r;
}

bool
ShotHttpSender::OnStart(void) {
	AppLog("ShotHttpSender OnStarts");
	return true;
}

void
ShotHttpSender::OnStop(void) {
	AppLog("ShotHttpSender OnStop");
}

void
ShotHttpSender::OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs) {

		AppLog("OnUserEventReceivedN");

		result r = E_SUCCESS;

		Thread::GetCurrentThread()->Sleep(500);

		shot = store->GetLastShot();

		if (shot == null) {
			SendUserEvent(1, null);
			return;
		}

		AppLog("Sending %S", shot->GetName()->GetPointer());

		String* uri = new String(L"http://192.168.0.184:8080/beholder-master/post");
		HttpHeader* pHeader= null;
		HttpTransaction* pHttpTransaction = null;

		// Open a new Http Transaction within the HttpSession
		pHttpTransaction = session->OpenTransactionN();
		AppLog("Getting transacton %S", GetErrorMessage(GetLastResult()));

		// Add Listener
		// OnTransactionCompleted() will be called when response is arrived
		pHttpTransaction->AddHttpTransactionListener(*this);

		// Get Http Request
		HttpRequest* pHttpRequest = pHttpTransaction->GetRequest();

		// Set HTTP Method
		pHttpRequest->SetMethod(NET_HTTP_METHOD_POST);

		// Set Uri
		pHttpRequest->SetUri(*uri);

		// Fill HTTP Header
		pHeader = pHttpRequest->GetHeader();

		//Add a chunked field to header.
		pHeader->AddField(L"Transfer-Encoding", L"chunked");

		//Enable OnTransactionReadyToWrite()
		r = pHttpTransaction->EnableTransactionReadyToWrite();
		AppLog("Enable write: %S", GetErrorMessage(r));

		//Set a Body to Request.

		ByteBuffer* data = shot->GetBytes();
		ByteBuffer* portion = new ByteBuffer();
		portion -> Construct(3);
		while(portion->GetPosition()<3) {
			byte b;
			data->GetByte(b);
			portion->SetByte(b);
		}
		portion->Flip();

		r = pHttpRequest->WriteBody(*portion);
		AppLog("Write result: %S", GetErrorMessage(r));

		// Submit a request with chunked mode
		r = pHttpTransaction->Submit();
		AppLog("Submit result: %S", GetErrorMessage(r));

		delete portion;
		delete uri;

}

void
ShotHttpSender::SendShot(Shot* shot) {
//    Construct();
//    Start();
//    IList* shotList = new ArrayList();
//    Object* obj = null;
//    obj = storage->GetLastShot();
//    shotList->Add(*shot);
//    SendUserEvent(1, shotList);
}
